using CollabApp.Domain.Services.Game;
using CollabApp.Application.Interfaces;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace CollabApp.Application.Services.Game;

/// <summary>
/// 地图缩圈服务实现
/// 负责处理游戏后期的地图缩小机制，增加游戏紧张感
/// </summary>
public class MapShrinkingService : IMapShrinkingService
{
    private readonly IRedisService _redisService;
    private readonly IPlayerStateService _playerStateService;
    private readonly ITerritoryService _territoryService;
    private readonly IGameStateService _gameStateService;
    private readonly ILogger<MapShrinkingService> _logger;

    /// <summary>
    /// 缩圈机制常量
    /// </summary>
    private static class ShrinkingConstants
    {
        public const int ShrinkingTriggerSeconds = 30; // 最后30秒开始缩圈
        public const int TotalShrinkingDuration = 30; // 缩圈总持续时间30秒
        public const float InitialMapRadius = 500f; // 初始地图半径
        public const float FinalSafeZoneRadius = 150f; // 最终安全区半径
        public const float DangerZoneDamagePerSecond = 5.0f; // 危险区域每秒伤害
        public const float ShrinkingSpeed = (InitialMapRadius - FinalSafeZoneRadius) / TotalShrinkingDuration; // 缩圈速度
    }

    /// <summary>
    /// Redis键模板
    /// </summary>
    private static class RedisKeys
    {
        public const string MapShrinkingStatus = "game:{0}:shrinking:status";
        public const string ShrinkingStages = "game:{0}:shrinking:stages";
        public const string PlayersInDangerZone = "game:{0}:shrinking:danger_players";
        public const string AffectedTerritories = "game:{0}:shrinking:affected_territories";
    }

    public MapShrinkingService(
        IRedisService redisService,
        IPlayerStateService playerStateService,
        ITerritoryService territoryService,
        IGameStateService gameStateService,
        ILogger<MapShrinkingService> logger)
    {
        _redisService = redisService;
        _playerStateService = playerStateService;
        _territoryService = territoryService;
        _gameStateService = gameStateService;
        _logger = logger;
    }

    /// <summary>
    /// 检查是否应该开始地图缩圈
    /// </summary>
    public async Task<bool> ShouldStartShrinkingAsync(Guid gameId)
    {
        try
        {
            var gameState = await _gameStateService.GetGameStateAsync(gameId);
            if (gameState == null || gameState.Status != CollabApp.Domain.Entities.Game.GameStatus.Playing)
            {
                return false;
            }

            // 检查剩余时间是否<=30秒
            var remainingTime = gameState.RemainingTime;
            var shouldStart = remainingTime.HasValue && remainingTime.Value.TotalSeconds <= ShrinkingConstants.ShrinkingTriggerSeconds;

            // 检查是否已经开始缩圈
            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            var existingStatus = await _redisService.GetAsync<MapShrinkingStatus>(statusKey);
            if (existingStatus != null && existingStatus.IsShrinking)
            {
                return false; // 已经在缩圈中
            }

            _logger.LogDebug("地图缩圈检查 - GameId: {GameId}, RemainingTime: {RemainingTime}s, ShouldStart: {ShouldStart}",
                gameId, remainingTime, shouldStart);

            return shouldStart;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查地图缩圈条件失败 - GameId: {GameId}", gameId);
            return false;
        }
    }

    /// <summary>
    /// 开始地图缩圈
    /// </summary>
    public async Task<ShrinkingStartResult> StartMapShrinkingAsync(Guid gameId)
    {
        try
        {
            var gameState = await _gameStateService.GetGameStateAsync(gameId);
            if (gameState?.Status != CollabApp.Domain.Entities.Game.GameStatus.Playing)
            {
                return new ShrinkingStartResult
                {
                    Success = false,
                    Errors = { "游戏状态不正确，无法开始缩圈" }
                };
            }

            // 检查是否已经在缩圈
            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            var existingStatus = await _redisService.GetAsync<MapShrinkingStatus>(statusKey);
            if (existingStatus != null && existingStatus.IsShrinking)
            {
                return new ShrinkingStartResult
                {
                    Success = false,
                    Errors = { "地图已经在缩圈中" }
                };
            }

            var startTime = DateTime.UtcNow;
            var mapCenter = new Position { X = 500f, Y = 500f }; // 地图中心点

            // 创建初始和最终安全区域
            var initialSafeZone = new SafeZoneInfo
            {
                CenterX = mapCenter.X,
                CenterY = mapCenter.Y,
                Radius = ShrinkingConstants.InitialMapRadius,
                Type = SafeZoneType.Circle
            };

            var finalSafeZone = new SafeZoneInfo
            {
                CenterX = mapCenter.X,
                CenterY = mapCenter.Y,
                Radius = ShrinkingConstants.FinalSafeZoneRadius,
                Type = SafeZoneType.Circle
            };

            // 创建缩圈状态
            var shrinkingStatus = new MapShrinkingStatus
            {
                IsShrinking = true,
                StartTime = startTime,
                CurrentSafeZone = initialSafeZone,
                TargetSafeZone = finalSafeZone,
                Progress = 0f,
                Phase = ShrinkingPhase.Stage1,
                RemainingSeconds = ShrinkingConstants.TotalShrinkingDuration,
                DangerZoneDamage = ShrinkingConstants.DangerZoneDamagePerSecond,
                PlayersInDangerZoneCount = 0,
                LastUpdateTime = startTime
            };

            // 保存缩圈状态到Redis
            await _redisService.SetAsync(statusKey, shrinkingStatus, TimeSpan.FromMinutes(10));

            // 获取所有玩家，检查哪些玩家受影响
            var allPlayers = await _playerStateService.GetAllPlayerStatesAsync(gameId);
            var affectedPlayerIds = new List<Guid>();

            foreach (var player in allPlayers)
            {
                var safetyResult = await CheckPositionSafetyAsync(gameId, player.CurrentPosition);
                if (!safetyResult.IsSafe)
                {
                    affectedPlayerIds.Add(player.PlayerId);
                }
            }

            // 预计算受影响的领地
            await CalculateAffectedTerritoriesAsync(gameId, initialSafeZone, finalSafeZone);

            var result = new ShrinkingStartResult
            {
                Success = true,
                StartTime = startTime,
                InitialSafeZone = initialSafeZone,
                FinalSafeZone = finalSafeZone,
                TotalDurationSeconds = ShrinkingConstants.TotalShrinkingDuration,
                DangerZoneDamagePerSecond = ShrinkingConstants.DangerZoneDamagePerSecond,
                AffectedPlayerIds = affectedPlayerIds,
                Messages = 
                {
                    "地图开始缩圈！",
                    $"安全区域将在{ShrinkingConstants.TotalShrinkingDuration}秒内缩小到半径{ShrinkingConstants.FinalSafeZoneRadius}",
                    "待在危险区域外会持续受到伤害",
                    "快速向地图中心移动！"
                }
            };

            _logger.LogInformation("地图缩圈开始 - GameId: {GameId}, 初始半径: {InitialRadius}, 最终半径: {FinalRadius}, 受影响玩家: {AffectedCount}",
                gameId, initialSafeZone.Radius, finalSafeZone.Radius, affectedPlayerIds.Count);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "开始地图缩圈失败 - GameId: {GameId}", gameId);
            return new ShrinkingStartResult
            {
                Success = false,
                Errors = { "开始缩圈时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 更新地图缩圈状态
    /// </summary>
    public async Task<ShrinkingUpdateResult> UpdateMapShrinkingAsync(Guid gameId)
    {
        try
        {
            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            var status = await _redisService.GetAsync<MapShrinkingStatus>(statusKey);

            if (status == null || !status.IsShrinking)
            {
                return new ShrinkingUpdateResult
                {
                    Success = false,
                    Warnings = { "地图未在缩圈中" }
                };
            }

            var now = DateTime.UtcNow;
            var elapsedSeconds = (float)(now - status.StartTime!.Value).TotalSeconds;
            var progress = Math.Min(elapsedSeconds / ShrinkingConstants.TotalShrinkingDuration, 1.0f);
            var remainingSeconds = Math.Max(ShrinkingConstants.TotalShrinkingDuration - (int)elapsedSeconds, 0);

            // 计算当前安全区域大小
            var currentRadius = ShrinkingConstants.InitialMapRadius - 
                               (ShrinkingConstants.InitialMapRadius - ShrinkingConstants.FinalSafeZoneRadius) * progress;

            var currentSafeZone = new SafeZoneInfo
            {
                CenterX = status.CurrentSafeZone.CenterX,
                CenterY = status.CurrentSafeZone.CenterY,
                Radius = currentRadius,
                Type = SafeZoneType.Circle
            };

            // 确定当前阶段
            var currentPhase = DetermineShrinkingPhase(progress);

            // 检查所有玩家位置安全性
            var allPlayers = await _playerStateService.GetAllPlayerStatesAsync(gameId);
            var playersInDanger = new List<Guid>();
            var eliminatedTerritoriesCount = 0;
            var eliminatedArea = 0f;

            foreach (var player in allPlayers)
            {
                var safetyResult = await CheckPositionSafetyAsync(gameId, player.CurrentPosition);
                if (!safetyResult.IsSafe)
                {
                    playersInDanger.Add(player.PlayerId);
                    
                    // 处理危险区域伤害
                    var damageResult = await ProcessDangerZoneDamageAsync(gameId, player.PlayerId, player.CurrentPosition);
                    if (damageResult.Success && damageResult.PlayerDied)
                    {
                        _logger.LogInformation("玩家 {PlayerId} 在危险区域死亡", player.PlayerId);
                    }
                }
            }

            // 计算消除的领地
            var affectedTerritories = await GetAffectedTerritoriesAsync(gameId);
            eliminatedTerritoriesCount = affectedTerritories.Count(t => t.CompletelyEliminated);
            eliminatedArea = affectedTerritories.Sum(t => t.LostArea);

            // 更新状态
            status.CurrentSafeZone = currentSafeZone;
            status.Progress = progress;
            status.Phase = currentPhase;
            status.RemainingSeconds = remainingSeconds;
            status.PlayersInDangerZoneCount = playersInDanger.Count;
            status.LastUpdateTime = now;

            // 保存更新后的状态
            await _redisService.SetAsync(statusKey, status, TimeSpan.FromMinutes(10));

            // 保存危险区域玩家列表
            var dangerPlayersKey = string.Format(RedisKeys.PlayersInDangerZone, gameId);
            await _redisService.SetAsync(dangerPlayersKey, playersInDanger, TimeSpan.FromMinutes(5));

            var result = new ShrinkingUpdateResult
            {
                Success = true,
                CurrentSafeZone = currentSafeZone,
                Progress = progress,
                RemainingSeconds = remainingSeconds,
                CurrentPhase = currentPhase,
                PlayersInDangerZone = playersInDanger,
                EliminatedTerritoriesCount = eliminatedTerritoriesCount,
                EliminatedTerritoryArea = eliminatedArea,
                UpdateDetails = 
                {
                    $"缩圈进度: {progress:P1}",
                    $"当前安全区半径: {currentRadius:F1}",
                    $"危险区域玩家数: {playersInDanger.Count}",
                    $"消除领地数: {eliminatedTerritoriesCount}"
                }
            };

            // 检查是否缩圈完成
            if (progress >= 1.0f || remainingSeconds <= 0)
            {
                await CompleteShrinkingAsync(gameId, status);
                result.UpdateDetails.Add("地图缩圈完成！");
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新地图缩圈状态失败 - GameId: {GameId}", gameId);
            return new ShrinkingUpdateResult
            {
                Success = false,
                Warnings = { "更新缩圈状态时发生错误" }
            };
        }
    }

    /// <summary>
    /// 获取当前地图缩圈状态
    /// </summary>
    public async Task<MapShrinkingStatus> GetShrinkingStatusAsync(Guid gameId)
    {
        try
        {
            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            var status = await _redisService.GetAsync<MapShrinkingStatus>(statusKey);
            
            return status ?? new MapShrinkingStatus
            {
                IsShrinking = false,
                Phase = ShrinkingPhase.NotStarted
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取地图缩圈状态失败 - GameId: {GameId}", gameId);
            return new MapShrinkingStatus
            {
                IsShrinking = false,
                Phase = ShrinkingPhase.NotStarted
            };
        }
    }

    /// <summary>
    /// 计算位置是否在安全区域内
    /// </summary>
    public async Task<PositionSafetyResult> CheckPositionSafetyAsync(Guid gameId, Position position)
    {
        try
        {
            var status = await GetShrinkingStatusAsync(gameId);
            
            if (!status.IsShrinking)
            {
                // 如果没有缩圈，所有位置都是安全的
                return new PositionSafetyResult
                {
                    IsSafe = true,
                    DistanceToSafeZone = 0f,
                    DistanceToCenter = 0f,
                    DangerLevel = 0f,
                    EstimatedTimeToSafety = 0f
                };
            }

            var safeZone = status.CurrentSafeZone;
            var distanceToCenter = CalculateDistance(position, new Position 
            { 
                X = safeZone.CenterX, 
                Y = safeZone.CenterY 
            });

            var isSafe = distanceToCenter <= safeZone.Radius;
            var distanceToSafeZone = Math.Max(0, distanceToCenter - safeZone.Radius);
            var dangerLevel = isSafe ? 0f : Math.Min(distanceToSafeZone / safeZone.Radius, 1f);

            Position? nearestSafePosition = null;
            var estimatedTimeToSafety = 0f;

            if (!isSafe)
            {
                // 计算最近的安全位置
                var angle = Math.Atan2(position.Y - safeZone.CenterY, position.X - safeZone.CenterX);
                nearestSafePosition = new Position
                {
                    X = safeZone.CenterX + (float)(Math.Cos(angle) * safeZone.Radius),
                    Y = safeZone.CenterY + (float)(Math.Sin(angle) * safeZone.Radius)
                };

                // 预估到达安全区域的时间（假设移动速度150像素/秒）
                const float playerSpeed = 150f;
                estimatedTimeToSafety = distanceToSafeZone / playerSpeed;
            }

            return new PositionSafetyResult
            {
                IsSafe = isSafe,
                DistanceToSafeZone = distanceToSafeZone,
                DistanceToCenter = distanceToCenter,
                NearestSafePosition = nearestSafePosition,
                DangerLevel = dangerLevel,
                EstimatedTimeToSafety = estimatedTimeToSafety
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查位置安全性失败 - GameId: {GameId}, Position: ({X}, {Y})", 
                gameId, position.X, position.Y);
            
            return new PositionSafetyResult
            {
                IsSafe = true, // 出错时默认安全，避免误伤
                DangerLevel = 0f
            };
        }
    }

    /// <summary>
    /// 处理玩家在危险区域的伤害
    /// </summary>
    public async Task<DangerZoneDamageResult> ProcessDangerZoneDamageAsync(Guid gameId, Guid playerId, Position currentPosition)
    {
        try
        {
            var safetyResult = await CheckPositionSafetyAsync(gameId, currentPosition);
            
            if (safetyResult.IsSafe)
            {
                return new DangerZoneDamageResult
                {
                    Success = true,
                    PlayerId = playerId,
                    DamageDealt = 0f,
                    PlayerDied = false,
                    CurrentHealthPercentage = 1f,
                    TimeInDangerZone = 0f,
                    DamageType = DangerZoneDamageType.Continuous
                };
            }

            // 计算伤害（基础伤害 + 根据危险级别调整）
            var baseDamage = ShrinkingConstants.DangerZoneDamagePerSecond;
            var dangerMultiplier = 1f + safetyResult.DangerLevel; // 越远离安全区伤害越高
            var finalDamage = baseDamage * dangerMultiplier;

            // 获取玩家当前状态
            var playerState = await _playerStateService.GetPlayerStateAsync(gameId, playerId);
            if (playerState == null || playerState.State == PlayerDrawingState.Dead)
            {
                return new DangerZoneDamageResult
                {
                    Success = false,
                    PlayerId = playerId,
                    Errors = { "玩家状态异常或已死亡" }
                };
            }

            // 应用伤害（这里简化处理，实际应该有血量系统）
            var playerDied = safetyResult.DangerLevel > 0.8f && safetyResult.DistanceToSafeZone > 100f;
            
            if (playerDied)
            {
                // 玩家因缩圈死亡
                await _playerStateService.HandlePlayerDeathAsync(gameId, playerId, "缩圈伤害", null);
            }

            var result = new DangerZoneDamageResult
            {
                Success = true,
                PlayerId = playerId,
                DamageDealt = finalDamage,
                PlayerDied = playerDied,
                CurrentHealthPercentage = playerDied ? 0f : Math.Max(0.1f, 1f - safetyResult.DangerLevel),
                TimeInDangerZone = 1f, // 简化为1秒
                DamageType = DangerZoneDamageType.Continuous
            };

            if (playerDied)
            {
                result.Warnings.Add("您在危险区域停留过久，已经死亡");
            }
            else
            {
                result.Warnings.Add($"您正在危险区域内，每秒受到{finalDamage:F1}点伤害");
                result.Warnings.Add($"预计{safetyResult.EstimatedTimeToSafety:F1}秒后可到达安全区域");
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理危险区域伤害失败 - GameId: {GameId}, PlayerId: {PlayerId}", gameId, playerId);
            return new DangerZoneDamageResult
            {
                Success = false,
                PlayerId = playerId,
                Errors = { "处理伤害时发生错误" }
            };
        }
    }

    /// <summary>
    /// 获取缩圈影响的领地列表
    /// </summary>
    public async Task<List<AffectedTerritoryInfo>> GetAffectedTerritoriesAsync(Guid gameId)
    {
        try
        {
            var affectedKey = string.Format(RedisKeys.AffectedTerritories, gameId);
            var cached = await _redisService.GetAsync<List<AffectedTerritoryInfo>>(affectedKey);
            
            if (cached != null)
            {
                return cached;
            }

            // 如果没有缓存，重新计算
            var status = await GetShrinkingStatusAsync(gameId);
            if (!status.IsShrinking)
            {
                return new List<AffectedTerritoryInfo>();
            }

            var allPlayers = await _playerStateService.GetAllPlayerStatesAsync(gameId);
            var affectedTerritories = new List<AffectedTerritoryInfo>();

            foreach (var player in allPlayers)
            {
                var territoryInfo = await _territoryService.CalculatePlayerTerritoryAsync(gameId, player.PlayerId);
                if (territoryInfo?.TerritoryBoundary?.Any() == true)
                {
                    var originalArea = territoryInfo.CurrentArea;
                    var remainingArea = CalculateRemainingTerritoryArea(territoryInfo.TerritoryBoundary, status.CurrentSafeZone);
                    var lostArea = Math.Max(0, (float)originalArea - remainingArea);
                    
                    var affectedInfo = new AffectedTerritoryInfo
                    {
                        PlayerId = player.PlayerId,
                        PlayerName = player.PlayerName,
                        TerritoryBoundary = territoryInfo.TerritoryBoundary,
                        OriginalArea = (float)originalArea,
                        RemainingArea = remainingArea,
                        LostArea = lostArea,
                        CompletelyEliminated = remainingArea <= 0.01f
                    };

                    affectedTerritories.Add(affectedInfo);
                }
            }

            // 缓存5分钟
            await _redisService.SetAsync(affectedKey, affectedTerritories, TimeSpan.FromMinutes(5));
            return affectedTerritories;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取受影响领地失败 - GameId: {GameId}", gameId);
            return new List<AffectedTerritoryInfo>();
        }
    }

    /// <summary>
    /// 停止地图缩圈
    /// </summary>
    public async Task<bool> StopMapShrinkingAsync(Guid gameId)
    {
        try
        {
            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            var status = await _redisService.GetAsync<MapShrinkingStatus>(statusKey);

            if (status != null)
            {
                status.IsShrinking = false;
                status.Phase = ShrinkingPhase.Completed;
                await _redisService.SetAsync(statusKey, status, TimeSpan.FromMinutes(5));
            }

            // 清理相关缓存
            var dangerPlayersKey = string.Format(RedisKeys.PlayersInDangerZone, gameId);
            var affectedKey = string.Format(RedisKeys.AffectedTerritories, gameId);
            var stagesKey = string.Format(RedisKeys.ShrinkingStages, gameId);
            
            await Task.WhenAll(
                _redisService.KeyDeleteAsync(dangerPlayersKey),
                _redisService.KeyDeleteAsync(affectedKey),
                _redisService.KeyDeleteAsync(stagesKey)
            );

            _logger.LogInformation("地图缩圈已停止 - GameId: {GameId}", gameId);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "停止地图缩圈失败 - GameId: {GameId}", gameId);
            return false;
        }
    }

    /// <summary>
    /// 预测缩圈路径和时间点
    /// </summary>
    public Task<ShrinkingPrediction> PredictShrinkingPathAsync(Guid gameId)
    {
        try
        {
            var mapCenter = new Position { X = 500f, Y = 500f };
            
            var stages = new List<ShrinkingStage>
            {
                new ShrinkingStage
                {
                    StageNumber = 1,
                    StartTime = 0,
                    Duration = 10,
                    StartSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = ShrinkingConstants.InitialMapRadius,
                        Type = SafeZoneType.Circle
                    },
                    EndSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = 350f,
                        Type = SafeZoneType.Circle
                    },
                    ShrinkingSpeed = 15f,
                    DangerZoneDamage = 3f
                },
                new ShrinkingStage
                {
                    StageNumber = 2,
                    StartTime = 10,
                    Duration = 10,
                    StartSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = 350f,
                        Type = SafeZoneType.Circle
                    },
                    EndSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = 250f,
                        Type = SafeZoneType.Circle
                    },
                    ShrinkingSpeed = 10f,
                    DangerZoneDamage = 5f
                },
                new ShrinkingStage
                {
                    StageNumber = 3,
                    StartTime = 20,
                    Duration = 10,
                    StartSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = 250f,
                        Type = SafeZoneType.Circle
                    },
                    EndSafeZone = new SafeZoneInfo 
                    { 
                        CenterX = mapCenter.X, 
                        CenterY = mapCenter.Y, 
                        Radius = ShrinkingConstants.FinalSafeZoneRadius,
                        Type = SafeZoneType.Circle
                    },
                    ShrinkingSpeed = 10f,
                    DangerZoneDamage = 8f
                }
            };

            var criticalMoments = new List<CriticalMoment>
            {
                new CriticalMoment
                {
                    TimePoint = 0,
                    EventType = CriticalEventType.ShrinkingStart,
                    Description = "地图开始缩圈",
                    RiskLevel = 2
                },
                new CriticalMoment
                {
                    TimePoint = 10,
                    EventType = CriticalEventType.ShrinkingAccelerate,
                    Description = "缩圈速度加快",
                    RiskLevel = 3
                },
                new CriticalMoment
                {
                    TimePoint = 20,
                    EventType = CriticalEventType.FinalSafeZone,
                    Description = "进入最终缩圈阶段",
                    RiskLevel = 4
                },
                new CriticalMoment
                {
                    TimePoint = 30,
                    EventType = CriticalEventType.GameEnding,
                    Description = "游戏即将结束",
                    RiskLevel = 5
                }
            };

            var prediction = new ShrinkingPrediction
            {
                Stages = stages,
                TotalDurationSeconds = ShrinkingConstants.TotalShrinkingDuration,
                FinalSafeZone = new SafeZoneInfo 
                { 
                    CenterX = mapCenter.X, 
                    CenterY = mapCenter.Y, 
                    Radius = ShrinkingConstants.FinalSafeZoneRadius,
                    Type = SafeZoneType.Circle
                },
                CriticalMoments = criticalMoments
            };

            return Task.FromResult(prediction);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "预测缩圈路径失败 - GameId: {GameId}", gameId);
            return Task.FromResult(new ShrinkingPrediction());
        }
    }

    #region 私有辅助方法

    /// <summary>
    /// 计算两点间距离
    /// </summary>
    private static float CalculateDistance(Position pos1, Position pos2)
    {
        var dx = pos1.X - pos2.X;
        var dy = pos1.Y - pos2.Y;
        return (float)Math.Sqrt(dx * dx + dy * dy);
    }

    /// <summary>
    /// 根据进度确定缩圈阶段
    /// </summary>
    private static ShrinkingPhase DetermineShrinkingPhase(float progress)
    {
        return progress switch
        {
            < 0.33f => ShrinkingPhase.Stage1,
            < 0.66f => ShrinkingPhase.Stage2,
            < 1.0f => ShrinkingPhase.FinalStage,
            _ => ShrinkingPhase.Completed
        };
    }

    /// <summary>
    /// 计算领地在安全区域内的剩余面积
    /// </summary>
    private static float CalculateRemainingTerritoryArea(List<Position> territoryBoundary, SafeZoneInfo safeZone)
    {
        try
        {
            // 简化计算：检查领地边界点在安全区内的比例
            if (!territoryBoundary.Any()) return 0f;

            var pointsInSafeZone = 0;
            var center = new Position { X = safeZone.CenterX, Y = safeZone.CenterY };

            foreach (var point in territoryBoundary)
            {
                var distance = CalculateDistance(point, center);
                if (distance <= safeZone.Radius)
                {
                    pointsInSafeZone++;
                }
            }

            var ratio = (float)pointsInSafeZone / territoryBoundary.Count;
            
            // 使用简化的面积计算（实际应该使用多边形裁剪算法）
            var originalArea = CalculatePolygonArea(territoryBoundary);
            return originalArea * ratio;
        }
        catch
        {
            return 0f;
        }
    }

    /// <summary>
    /// 计算多边形面积（Shoelace公式）
    /// </summary>
    private static float CalculatePolygonArea(List<Position> polygon)
    {
        if (polygon.Count < 3) return 0;

        float area = 0;
        for (int i = 0; i < polygon.Count; i++)
        {
            int j = (i + 1) % polygon.Count;
            area += polygon[i].X * polygon[j].Y;
            area -= polygon[j].X * polygon[i].Y;
        }
        return Math.Abs(area) / 2.0f;
    }

    /// <summary>
    /// 预计算受影响的领地
    /// </summary>
    private async Task CalculateAffectedTerritoriesAsync(Guid gameId, SafeZoneInfo initialSafeZone, SafeZoneInfo finalSafeZone)
    {
        try
        {
            var allPlayers = await _playerStateService.GetAllPlayerStatesAsync(gameId);
            var affectedTerritories = new List<AffectedTerritoryInfo>();

            foreach (var player in allPlayers)
            {
                var territoryInfo = await _territoryService.CalculatePlayerTerritoryAsync(gameId, player.PlayerId);
                if (territoryInfo?.TerritoryBoundary?.Any() == true)
                {
                    var originalArea = territoryInfo.CurrentArea;
                    var finalRemainingArea = CalculateRemainingTerritoryArea(territoryInfo.TerritoryBoundary, finalSafeZone);
                    var lostArea = Math.Max(0, (float)originalArea - finalRemainingArea);
                    
                    var affectedInfo = new AffectedTerritoryInfo
                    {
                        PlayerId = player.PlayerId,
                        PlayerName = player.PlayerName,
                        TerritoryBoundary = territoryInfo.TerritoryBoundary,
                        OriginalArea = (float)originalArea,
                        RemainingArea = finalRemainingArea,
                        LostArea = lostArea,
                        CompletelyEliminated = finalRemainingArea <= 0.01f
                    };

                    affectedTerritories.Add(affectedInfo);
                }
            }

            // 缓存预计算结果
            var affectedKey = string.Format(RedisKeys.AffectedTerritories, gameId);
            await _redisService.SetAsync(affectedKey, affectedTerritories, TimeSpan.FromMinutes(10));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "预计算受影响领地失败 - GameId: {GameId}", gameId);
        }
    }

    /// <summary>
    /// 完成缩圈
    /// </summary>
    private async Task CompleteShrinkingAsync(Guid gameId, MapShrinkingStatus status)
    {
        try
        {
            status.IsShrinking = false;
            status.Phase = ShrinkingPhase.Completed;
            status.Progress = 1.0f;
            status.RemainingSeconds = 0;

            var statusKey = string.Format(RedisKeys.MapShrinkingStatus, gameId);
            await _redisService.SetAsync(statusKey, status, TimeSpan.FromMinutes(5));

            _logger.LogInformation("地图缩圈完成 - GameId: {GameId}", gameId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "完成缩圈处理失败 - GameId: {GameId}", gameId);
        }
    }

    #endregion
}
